#!/usr/bin/env perl

use strict;
use warnings;

use File::Basename;
use File::Spec::Functions;
use Test::More tests => 72;

my $test_dir = './tst';

`rm -rf $test_dir/*.obj`;

for my $tst_fn (glob(catfile($test_dir, '*.pr'))) {
  # Object file that is being executed
  my $tst_obj_fn  = replace_extension($tst_fn, "obj");
  # Expected output of execution
  my $exp_fn      = replace_extension($tst_fn, "exp");
  # File with expected errors in it
  my $err_fn      = replace_extension($tst_fn, "err");

  # Compile
  my $c_output    = `./my_compile.sh $tst_fn 2>&1`;

  # Run obj file if there is *.exp file that have result of execution
  if (-f $tst_obj_fn && -f $exp_fn) {
      # Do compilation
      # '2>&1' - To capture a command's STDERR and STDOUT together
      my $produced_output = `./mj_run.sh $tst_obj_fn 2>&1`;

      # Try to open exp file
      open my $fd, '<', $exp_fn;
      if (not defined $fd) {
        fail($!);
        next;
      }

      # Prepare strings for comparing
      my $expected_output = join "", <$fd>;
      close $fd;
      # We remove "n ms", so we always pass test when execution is the same
      $expected_output
        = $expected_output =~ s/^(Completion took).*$/$1/xms;
      $produced_output
        = $produced_output =~ s/^(Completion took).*$/$1/xms;

      # Compare them
      is($produced_output, $expected_output, $tst_fn);
  }
  elsif (-f $exp_fn) {
    fail($tst_fn);

  }
  # Check for expected errors during compilation
  if (-f $err_fn){
    # Open file
    open my $fd, '<', $err_fn;
    if (not defined $fd) {
      fail($!);
      next;
    }

    # Run check on all lines from *.err file
    while (my $expected_error_line = <$fd>) {
      chomp($expected_error_line);
      if ($c_output =~ m/$expected_error_line/m) {
        pass("$err_fn: Found: $expected_error_line");
      }
      else {
        fail("Didn't find: $expected_error_line");
        diag($c_output);
        diag($expected_error_line);
      }
    }
  }
  # Check are all counters printed like expected...
  my $c_expected_fn = replace_extension($tst_fn, "cnt");
  if (-f $c_expected_fn) {
    # Open file
    open my $fd, '<', $c_expected_fn;
    if (not defined $fd) {
      fail($!);
      next;
    }

    # Extract expected counts from file without new lines
    my @expected_counts = map { chomp; $_ } grep  { m/Count for/ } <$fd>;

    # Extract counts from our compiler output
    my @current_counts;
    my @count_for;
    while ($c_output
        =~ m/^ ( Count \s for \s ([^:]+?) \s* : \s* \d+ .*? ) $/gxms
      ) {
      # Current count line
      push @current_counts, $1;
      # It tells as what for
      push @count_for,      $2;
    }

    # Go through all counts and compare them
    for (my $i = 0; $i < @current_counts; $i++) {
      is($current_counts[$i], $expected_counts[$i], "$c_expected_fn: <$count_for[$i]> counts okey");
    }
  }
}

# sub replace_extension_with($orig_fn, $extension)
# replace extension with new one
sub replace_extension {
  my ($orig_fn, $extension) = @_;

  $orig_fn =~ s/\.[^.]+$/.$extension/;

  return $orig_fn;
}
